/*
 * Package il.ac.biu.cs.grossmm.impl.activeData
 * File SqlInspector.java
 * 
 * This is a part of presence service framework prototype. 
 * See javadoc for more information.
 *  
 * Copyright (C) 2006 Grossmann Mark
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package il.ac.biu.cs.grossmm.impl.activeData;

import il.ac.biu.cs.grossmm.api.OperationFailedException;
import il.ac.biu.cs.grossmm.api.data.Node;
import il.ac.biu.cs.grossmm.api.data.NodeType;
import il.ac.biu.cs.grossmm.api.data.Nodeset;
import il.ac.biu.cs.grossmm.api.data.Property;
import il.ac.biu.cs.grossmm.api.data.Unique;
import il.ac.biu.cs.grossmm.api.flow.NodeInspector;

import java.util.Set;

@SuppressWarnings("unchecked")
public class SqlInspector implements NodeInspector {

	public SqlInspector() {
	}

	public <N, S> Set<Node<S>> getSubnodes(Node<N> node, Nodeset<N, S> nodeset)
			throws OperationFailedException {
		int index = nodeset.index();
		SqlMapping m = ((SqlNodeBase<N>) node).mapping;

		return (Set) m.getSubnodes((SqlNodeBase) node, index);
	}

	public <N, P> P getValue(Node<N> node, Property<N, P> property)
			throws OperationFailedException {
		int index = property.index();
		SqlNodeBase<N> sqlNode = (SqlNodeBase<N>) node;

		SqlMapping m = sqlNode.mapping;
		Object[] s = m.getValues(sqlNode);

		return (P) s[index];
	}

	public <N, S, U> Node<S> getSubnode(Node<N> node, Nodeset<N, S> nodeSet,
			Unique<S, U> unique, U value) throws OperationFailedException {
		Set<SqlNodeBase<S>> set = (Set) getSubnodes(node, nodeSet);

		int index = nodeSet.index();

		for (SqlNodeBase<S> sqlNode : set) {
			SqlMapping m = sqlNode.mapping;
			Object val = m.getValues(sqlNode)[index];

			if (val == null)
				continue;

			if (val.equals(value))
				return sqlNode;
		}

		return null;
	}

	public String toString(Node node) {
		StringBuffer sb = new StringBuffer("\n");
		try {
			toStringBuffer(node, sb, "");
		} catch (OperationFailedException e) {
			return "[[" + e.getMessage() + "]]";
		}

		return sb.toString();
	}

	private void toStringBuffer(Node node, StringBuffer sb, String prefix)
			throws OperationFailedException {
		NodeType type = node.getNodeType();

		int numOfProps = type.propertiesNumber();

		for (int i = 0; i < numOfProps; i++) {
			Property property = type.property(i);
			Object value = getValue(node, property);
			sb.append(prefix);
			sb.append(property);
			sb.append(" = ");
			sb.append(value);
			sb.append("\n");
		}

		int numOfSets = type.propertiesNumber();

		String prefix2 = prefix + "   ";

		for (int i = 0; i < numOfSets; i++) {
			Nodeset nodeset = type.nodeset(i);
			Set<Node> subnodes = getSubnodes(node, nodeset);

			sb.append(prefix);
			sb.append(nodeset);
			sb.append(" = {\n");

			for (Node n : subnodes) {
				toStringBuffer(n, sb, prefix2);
			}

			sb.append("}\n");
		}
	}

}
